/**
 * 采用redis作为消息引擎，通过发布/订阅模式实现服务器对客户端的消息发送，及客户端对服务器的消息上报。
 * Created by macos on 14/11/7.
 */

var EventEmitter = require('events').EventEmitter.
util = require('util');

var _ = require('lodash'),
	async = require('async'),
	redis = require('redis');

var checksum = require('./checksum');

(function() {
	var root = this;
	var MessageQ = {};
	var clients = {};
  var publishClient = null;

	var _count = 0;
	var _config;

  /***
   * 将数字转换成低位的字符串形式的16进制字节
   * @param number
   * @returns {*}
   */
  function number2lowHex(number) {
    var hex = number.toString(16);

    if (hex.length < 8) {
      var fillLen = 8 - hex.length;
      for (var i = 0; i < fillLen; i++) {
        hex = "0" + hex;
      }
    }

    return hex;
  }

  /**
   * 回复客户端
   * @param type
   * @param sid
   * @param length
   * @param content
   * @param res
   */
  function sendMsgToClient(type, sid, length, content, res) {

    var result = {
      event: 'adda',
      type: type,
      sessionId: sid,
      len: length,
      content: content
    };

    if (length == null) delete result.len;

    res.writeObj(result, function (hexStr) {
      var buf = new Buffer(hexStr, 'hex');
      var checksumStr = checksum.checksum(buf, 0, buf.length);
      hexStr = hexStr + checksumStr;
      return hexStr;
    });
  }

	MessageQ.create = function(config) {

    config.port = config.port || 6379;
    config.host = config.host || 'localhost';
    config.db = config.db || 0;
    config.debug_mode = config.debug_mode || true;

		_config = config;

    publishClient = redis.createClient(_config.port, _config.host, _config.options);
    publishClient.select(_config.db);

    if (_config.password) {
      publishClient.auth(_config.password);
    }
	}

	MessageQ.addChannel = function(channel) {
    sails.log.debug('Add channel:',channel);

		var _client = redis.createClient(_config.port, _config.host, _config.options);
		_client.select(_config.db);

		if (_config.password) {
			_client.auth(_config.password);
		}

		_client.subscribe(channel);
		clients[channel] = _client;
	}

	MessageQ.onChannel = function(channel, callback) {
		callback = callback || function() {};

		var _client = clients[channel];

    sails.log.debug(channel);
		_client.on('message', function(channel, message) {
			sails.log.debug(channel, ':',  message);
			callback(null, message);
		});

		_client.on("error", function(err) {
			callback(err);
		});

	}

  MessageQ.removeChannel = function(channel) {
    var _client = clients[channel];
    _client.removeAllListeners("message");
    clients.pop(channel);

  }

  /**
   *
   * @param device
   * @param text
   * @param callback err status。0, 客户端未连接，1，已发送客户端，2， 客户端回复成功，3，客户端回复失败。
   */
	MessageQ.sendClient = function(device, text, callback) {
		callback = callback || function() {};

    var channel = 'channel:' + device.uuid;
    var sid = '0' + (Date.now()).toString(16);
    var msg = {sessionId:sid, content:text};
    publishClient.publish(channel, JSON.stringify(msg), function(err, reply){
      if (err) {
        callback(err);
        return;
      }

      if (reply === 0) {
        callback(null, 0);
      } else {
        callback(null, 1);
      }

      //记录消息会话
      msg.toUUID = device.uuid;
      Send.create(msg).exec(function (err, result) {
        if (err) {
          sails.log.error(err);
          return;
        }
      });

    });

	}

  /**
   * 补发待发送状态的消息
   * @param session session会话对象
   * @param client net.socket 客户端socket连接对象
   * @constructor
   */
  MessageQ.SendHistoryRetry = function(session, client) {

    async.waterfall([

      function(next) {
        Send.find({toUUID:session.uuid, status:0}).exec(function(err, result){
          if (err) {
            return next(err);
          }
          next(null, result)
        });
      },

      function(sendMessages, next) {

        async.each(sendMessages, function(sendMessage, callback){
          var contentBuffer = new Buffer(sendMessage.content);
          var lenHex = number2lowHex(contentBuffer.length);
          sendMsgToClient('00', sendMessage.sessionId, lenHex, contentBuffer.toString('hex'), client);
          next();
        }, function(err){
          next(err);
        })

      }

    ], function(err, result){
      if (err) {
        sails.log.error(err);
      }
    });

  }

	module.exports = MessageQ;
})();